package Game;

import java.util.Random;
import java.util.Vector;

import Map.Tuile;
import Unite.Legion;
import Unite.Unit;

public class Combat {

	/**
	 * Premier round de la bataille
	 * 
	 * @param attackingLegion
	 * @param defendingLegion
	 * @param tuile
	 */
	public static void fightOneRound(TableValeurs val, Legion attackingLegion,
			Legion defendingLegion, Tuile tuile) {

		Vector<Legion> allLegions = new Vector<Legion>();
		allLegions.add(attackingLegion);
		allLegions.add(defendingLegion);

		PairingTable pairingTable = calculateRatio(attackingLegion,
				defendingLegion);
		PairingTable resultsTable = calculateResults(val, attackingLegion,
				defendingLegion, tuile, pairingTable);

		determineDeath(allLegions, resultsTable);
	}

	/**
	 * Calcul les ratios pour le combat
	 * 
	 * @param attackingLegion
	 * @param defendingLegion
	 * @return
	 */
	public static PairingTable calculateRatio(Legion attackingLegion,
			Legion defendingLegion) {

		PairingTable pairingTable = new PairingTable();
		Vector<Legion> allLegions = new Vector<Legion>();
		allLegions.add(attackingLegion);
		allLegions.add(defendingLegion);

		for (Legion currentLegion : allLegions)
			for (Legion otherLegion : allLegions)
				if (!currentLegion.equals(otherLegion))
					for (Unit unitCurrent : currentLegion.getUnits())
						for (Unit unitOpponent : otherLegion.getUnits())
							pairingTable.pair(unitCurrent, unitOpponent,
									(double) unitOpponent.getWeight()
											/ (double) otherLegion.getWeight());

		return pairingTable;
	}

	/**
	 * Calcul les resultats de la bataille
	 * 
	 * @param attackingLegion
	 * @param defendingLegion
	 * @param tuile
	 * @param pairingTable
	 * @return
	 */
	public static PairingTable calculateResults(TableValeurs val,
			Legion attackingLegion, Legion defendingLegion, Tuile tuile,
			PairingTable pairingTable) {

		PairingTable resultsTable = new PairingTable();
		Vector<Legion> allLegions = new Vector<Legion>();
		allLegions.add(attackingLegion);
		allLegions.add(defendingLegion);

		for (Legion currentLegion : allLegions)
			for (Legion otherLegion : allLegions)
				if (!currentLegion.equals(otherLegion))
					for (Unit unitCurrent : currentLegion.getUnits())
						for (Unit unitOpponent : otherLegion.getUnits()) {
							double result = calculateDamage(val,
									pairingTable.get(unitCurrent.getId(),
											unitOpponent.getId()), unitCurrent,
									unitOpponent, tuile);
							resultsTable.set(unitCurrent.getId(),
									unitOpponent.getId(), result);
						}

		return resultsTable;

	}

	/**
	 * Calcul les dommages des unites
	 * 
	 * @param ratio
	 * @param unitCurrent
	 * @param unitOpponent
	 * @param tuile
	 * @return les dommages
	 */
	private static double calculateDamage(TableValeurs tableValeurs,
			double ratio, Unit unitCurrent, Unit unitOpponent, Tuile tuile) {
		return ratio
				* unitCurrent.getPower()
				* tableValeurs.getUnitDamage(unitCurrent.getClasseId(),
						unitOpponent.getClasseId())
				* tableValeurs.getTerrainDamage(unitCurrent.getClasseId(),
						tuile.getTerrainId());
	}

	/**
	 * Determine qui doit mourrir
	 * 
	 * @param allLegions
	 * @param resultsTable
	 */
	public static void determineDeath(Vector<Legion> allLegions,
			PairingTable resultsTable) {

		for (Legion lgCurrent : allLegions)
			for (Unit unitCurrent : lgCurrent.getUnits())
				if (randomDeath(resultsTable.getDamage(unitCurrent)))
					lgCurrent.setToRemove(unitCurrent);
	}

	/**
	 * @param damage
	 * @return
	 */
	private static boolean randomDeath(double damage) {
		Random r = new Random();
		double d = (r.nextGaussian() + 2) / 2.2;
		return (d < damage);
	}
}
